/**
 * @projectDescription	Client programm for messages exchange via ICQ 
 * @author 		Alexey MAGician Sergeev 
 * @version 	1.0.0
 */

///******************************

/**
 * Без этой глобальной переменной никак... =(
 * @type Object
 */ 
var mainMessagesWindow = undefined;
/**
 * А без этой крайне сложно...
 * @type Object
 */  
var mousePosition = undefined;

/**
 * Возвращает строку содержащую текщую дату
 *
 * @param 	showdate bool
 * @param	showtime bool
 * @param	format12 bool
 * @return 	string
 * @type	string
 */
function GetCurrentDate(showdate, showtime, format12) {
	if (format12 == undefined) {format12 = false;};
	if (showdate == undefined) {showdate = true;};
	if (showtime == undefined) {showtime = true;};
	
	var all=new Date();
	var datevalue = "";
	if (showdate) {
		datevalue = all.getDate() + "/" + (all.getMonth()+1) + "/" + all.getFullYear();
	} 
	
	var hours	= all.getHours();
	var minutes	= all.getMinutes();
	var seconds	= all.getSeconds();
	
	var timevalue = ""; 
	if (showtime) {
		timevalue = ((format12) ? ((hours>12) ? hours-12 : hours) : hours);
		timevalue+= ((minutes<10) ? ":0" : ":") + minutes;
		timevalue+= ((seconds<10) ? ":0" : ":") + seconds;
		if (format12) {
			timevalue+= " ";
			timevalue+= (hours>=12) ? "P.M." : "A.M.";
		}
	}
	
	return datevalue + ((showdate && showtime) ? " " : "") + timevalue;
};


/**
 * Добавляет сообщение в окно лога
 */ 
function AddLogMessage(message, status) {
	var logArea = $('#LogArea');
	var newLogMess = $('<div class="log_message">');
	newLogMess.html('<span class="log_date">&lt;' + GetCurrentDate(false) + '&gt;</span> ' + $('<div>').text(message).html()).css("color", ((status==undefined)? "#000" : "#F00")).appendTo(logArea);
	newLogMess.hover(function(){$(this).toggleClass("log_message_active");},function(){$(this).toggleClass("log_message_active");});
	newLogMess[0].scrollIntoView(false);
}

/**
 * AJAX  - Класс обмена сообщениями с сервером
 * 
 * @classDescription Класс обмена сообщениями с сервером
 * @constructor  
 */
function CAJAX(parentClass) 
{
	/**
	 * @type CAJAX
	 */
	var thisCAJAX 	= this;
	/**
	 * @type CMainMessagesWindow
	 */
	var parentClass = parentClass;
	var useMethod 	= 1;
	var variableName= undefined;
	var refreshTime = 2000;
	var ajaxphpfile = 'ajax_unit.php';
	var queryArray 	= new Array();
	var messages	= new Array();
	var queryIsRun 	= false;
	var useEncoding	= false;

	/**
	 * Конструктор класса
	 */
	this.__CAJAX = function () 
	{
	};
	
	/**
	 * Устанавливает метод обмена сообщениями
	 */ 
	this.setMethod = function(Method) 
	{
		if (Method == 1) {
			Method = 1;
		}else{
			Method = 0;		
		};
	};

	/**
	 * Запускает таймер до начала следующего обмена
	 */
	this.startQueryTimer = function () 
	{
		setTimeout(variableName + ".makeQuery()", refreshTime);
	};

	/**
	 * Установка запроса в очередь 
	 */
	this.MakeAJAXQuery = function(action, dopparams, callback, callbackParam) 
	{
	
		for (var i=0; i<queryArray.length; i++) {
			if ((action == queryArray[i].action)&&(action == "GetNewMessages")) {
				return undefined;
			};
		};
	
		var params = {action:undefined};
		params.action = (action != undefined) ? action : "test"; 
	
		if (dopparams != undefined) {
			for (var property in dopparams) {
				params[property] = dopparams[property];
			}
		}
		
		//Очередь на отправку...
		queryArray[queryArray.length] = {action: action, params: params, callback: callback, callbackParam : callbackParam};
	};

	/**
	 * Постановка в очередь отправки сообщений
	 */
	this.addMessageForSend = function(mesFor, mesText) 
	{
		messages[messages.length] = {mesFor : mesFor, mesText : mesText};
	};
	
	/**
	 * Вызывается при получении новых сообщений
	 */
	var resevedNewMessages = function(xml) 
	{
		var messages = $('new_messages > message', xml);
		var currentElement = undefined;
		var allMessagesIDs = "";
		
		if (messages.length == 0) {
			return undefined;
		}
		
		AddLogMessage('Ajax query return: ' + messages.length + ' new messages');
		
		for (var i=0; i<messages.length; i++) {
			currentElement = messages.eq(i);
			parentClass.newMessage(currentElement.attr('uin'),currentElement.text());
			allMessagesIDs = allMessagesIDs + currentElement.attr('id') + ",";
		}
		
		allMessagesIDs = allMessagesIDs.slice(0, -1);
		thisCAJAX.MakeAJAXQuery("newDeliveredMessages", {MessagesIDs : allMessagesIDs});
	};
	
	/**
	 * Функция вызываемая из "makeQuery" и раздающая результат запроса всем кто стоял в очереди
	 */ 
	var callBackFunction = function (strInput) 
	{
		//var xml = (useEncoding) ? : $(decryptRC4Str("_my_super_puper_key_", strInput)) : strInput;
		var xml = strInput;
		
		var oldqueryArray = new Array();
		
		for (var i=0; i<queryArray.length; i++) {
			oldqueryArray[i] = queryArray[i];
		}
		// TODO Возможный косяк
		// Обнуляем все очереди.... хоя может это надо делать и не тут.... =(
		queryArray 	= new Array();
		messages	= new Array();
		
		for (var i=0; i<oldqueryArray.length; i++) {
			if (oldqueryArray[i].callback != undefined) {
				oldqueryArray[i].callback(xml, oldqueryArray[i].callbackParam);
			};
		};
		
		queryIsRun = false;
	};

	/**
	 * Вызывается из таймера. Обработка очереди и посылка запроса серверу  
	 */
	this.makeQuery = function() 
	{
		if (queryIsRun) { // Уже запущено, бум ждать
			AddLogMessage("Query had already run");
			this.startQueryTimer();
			return;
		}
		
		this.MakeAJAXQuery("GetNewMessages", undefined, resevedNewMessages);
		
		// Очередь пустая...
		if ((queryArray.length == 0) && (messages.length == 0)) {
			this.startQueryTimer();
			return undefined;
		}

		var params = {actions: "", qerydate:GetCurrentDate()};
		var ParamsCount=0;
		
		// Если есть что делать, то делаем 
		if (queryArray.length != 0) {
			for (var i=0; i<queryArray.length; i++) {
				ParamsCount = i+1;
				var dopParams = queryArray[i].params;
	
				for (var property in dopParams) {
					if (property == "action") {
						params.actions = params.actions + dopParams.action + ",";
					}else{
						params["P"+i+"__"+property] = dopParams[property];
					}
				}
			}
		}
		// Если есть сообщения для отправки, то отправляем 
		if (messages.length != 0) {
			params["P"+ParamsCount+"__messCount"] = messages.length;
			params.actions = params.actions + "newMessagesForSend,"; 
			for (var i=0; i<messages.length; i++) {
				params["P"+ParamsCount+"__mestext_"+i] = messages[i].mesText;
				params["P"+ParamsCount+"__mesfor_"+i] = messages[i].mesFor;
			}
		}

		params.actions = params.actions.slice(0, -1);
		
		// Если только одно действие о приеме новых сообщений, то не выводим его в лог 
		if ((params.actions != "GetNewMessages")&&(params.actions != "GetUserContactList,GetNewMessages")) {
			AddLogMessage('Ajax query: ' + params.actions);
		}
		
		queryIsRun = true;
		// AJAX request
		if (useMethod == 1) {
			var val = $.get(ajaxphpfile, params, callBackFunction);
		} else {
			var val = $.post(ajaxphpfile, params, callBackFunction);
		};
		
		this.startQueryTimer();		
	};

	/**
	 * Инициализация таймера
	 */
	this.startTimer = function(variableNameIn, refreshTimeIn /* = 2 */) 
	{
		if (variableNameIn == undefined) {
			AddLogMessage('Undefined variable name! Timer not started!');
			return;		
		}
		// Установим время обновления, если было передано в параметре
		if(refreshTimeIn != undefined) {
			refreshTime = refreshTimeIn;
		}
		
		variableName = variableNameIn;
		this.makeQuery(); // Делает запрос и устанавливает таймер на повтор 
	};
	
	/**
	 * Установка времени обновления таймера
	 */
	this.setRefreshTime = function(time) 
	{
		refreshTime = time;
	};

	// Вызов конструктора 	
	this.__CAJAX();
};

/**
 * Класс стилей
 * @constructor
 */ 
function COutputStyles (parentClass) 
{
	var thisOutputStyles = this;
	var parentClass = parentClass;
	
	var stylesvalues = {
		contactnamecolor 	: "#00F",
		usernamecolor 		: "#F00",
		messagecolor 		: "#000"};

	/**
	 * Конструктор класса
	 */
	this.__COutputStyles = function () 
	{
	};
	/**
	 * @return Возвращает значене параметра стиля
	 * @param {string} fieldName
	 * @type string  
	 */
	this.getValue = function(fieldName) 
	{
		return stylesvalues[fieldName.toLowerCase()];
	};
	/**
	 * Устанавливает значение параметра стиля
	 * @param {string} fieldName
	 * @param {string} fieldValue
	 */
	this.setValue = function(fieldName, fieldValue) {	
		stylesvalues[fieldName.toLowerCase()] = fieldValue;
	};
	
	// Вызов конструктора
	this.__COutputStyles();
}

/**
 * Класс отображения статусов
 */ 
function CStatuses(parentClass) {
	var thisCStatuses	= this;
	var parentClass 	= parentClass;
	var AJAXQuery 		= parentClass.getAJAXQuery();
	var statusesArray 	= new Array();

	/**
	 * Конструктор класса
	 */
	this.__CStatuses = function() 
	{
		AJAXQuery.MakeAJAXQuery("GetAllStatuses",undefined, thisCStatuses.ajaxStatusesReturn);
	};
	/**
	 * @return Ссылка на объект обена AJAX
	 * @type Object
	 */
	this.getAJAXQuery = function() 
	{
		return AJAXQuery;
	};
	/**
	 * @return массив статусов
	 * @type array
	 */
	this.getStatusesArray = function() 
	{
		return statusesArray; 
	};
	/**
	 * @return Возвращает номер статуса по его ID
	 * @type integer
	 */
	var getStatusNum = function (id) 
	{
		for (var i=0; i<statusesArray.length; i++) {
			if (statusesArray[i].id == id) {
				return i;
			}
		}
		return undefined; 
	};
	/**
	 * @return Возвращает строку статуса
	 * @type string
	 */  
	this.getStatusName = function(id) 
	{
		var num = getStatusNum(id);
		if (num !=undefined) {
			return statusesArray[num].alias;
		} else {
			return '';
		}
	};
	/**
	 * @return Возвращает картинку статуса
	 * @type string
	 */ 
	this.getStatusPicture = function(id) 
	{
		var num = getStatusNum(id);
		if (num !=undefined) {
			return statusesArray[num].picture;
		} else {
			return '';
		}
	};
	/**
	 * Вызывается при успешном получении данных с сервера
	 */
	this.ajaxStatusesReturn = function(xml) 
	{
		var statuses = $("statuses > status",xml);
		var currentElement = undefined;
		
		AddLogMessage('Ajax query return: ' + statuses.length + ' statuses');
		
		for (var i=0; i<statuses.length; i++) {
			currentElement = statuses.eq(i);

			statusesArray[statusesArray.length] = 
				{
					id:			currentElement.attr('id'),
					alias:		currentElement.attr('alias'),
					picture:	currentElement.attr('picture'),
					isonline:	(currentElement.attr('isonline') == "1")
				};
		}
	};
	
	// Инициализация класса
	this.__CStatuses();
};

/**
 * Класс контекстного меню
 * @constructor
 */
function CContactMenu(parentClass, UIN) {
	var thisContactMenu = this;
	var parentClass 	= parentClass;
	var mainDiv			= undefined;
	var title			= undefined;
	var menupos			= undefined;

	/**
	 * Конструктор класса
	 */
	this.__CContactMenu = function()
	{
		mainDiv = $('<div class="contactMenu_mainWin"></div>').hide();
		title 	= $('<div class="contactMenu_title">Context menu</div>').appendTo(mainDiv);
		menupos = $('<ul class="contactMenu_items"><li>111</li><li>222</li><li>333</li><li>111</li><li>222</li><li>333</li></ul>').appendTo(mainDiv);
		
		$("li", menupos).addClass("contactMenu_item").hover(
			function() {$(this).toggleClass("contactMenu_hover");},
			function() {$(this).toggleClass("contactMenu_hover");}	
		);
	
		$("li", menupos).click(
				function() {
					alert($(this).text());
					}
				);
		
		$(document).bind('click', thisContactMenu.hideThisMenu);
	};
	/**
	 * @return Возвращает объект контекстного меню
	 * @type jquery
	 */
	this.getContactMenuWin = function() 
	{
		return mainDiv; 
	};
	/**
	 * Скрывает контекстное меню
	 */
	this.hideThisMenu = function() 
	{
		mainDiv.fadeOut(200);
	};
	// Инициализация класса
	this.__CContactMenu();
}; // CContactMenu


/**
 * Класс контакта
 * 
 * @param parentClass CContactList
 * @param UIN
 */
function CContact(parentClass, UIN) {
	var thisContact 	= this;
	/**
	 * @type CContactList
	 */
	var parentClass 	= parentClass;
	var AJAXQuery 		= parentClass.getAJAXQuery();
	var UIN 			= UIN;
	var contactFields 	= {};
	var isSelected 		= false;
	var isVisible 		= true;
	
	var contactContainer 	= undefined;
	var contactContainerTr 	= undefined;
	var contactStatus		= undefined;
	var contactText 		= undefined;
	var contextMenu 		= undefined;
	var ContextMenuWin 		= undefined; 

	/**
	 * Конструктор класса
	 */
	this.__CContact = function() 
	{
		contactContainer 	= $('<div class="contactContainer" oncontextmenu="$(this).trigger(\'myEventShowContactMenu\');return false;"></div>');
		contactContainerTr 	= $('<div class="contactContainerTr"></div>').appendTo(contactContainer); // Прозрачная область, В которой отображается имя и статус контакта
		contactStatus 		= $('<div class="contactStatus"></div>').appendTo(contactContainer);
		contactText 		= $('<div class="contactText"></div>').text(thisContact.getContactName()).appendTo(contactContainer);
	
		// Приделаем контекстное меню к конртакту
		contextMenu 	= new CContactMenu(thisContact, UIN);
		ContextMenuWin 	= contextMenu.getContactMenuWin();
		ContextMenuWin.appendTo($('body'));
		
		// Обрабоотка подсветки при наведении 
		contactContainer.hover(
			function() {$(contactContainerTr).addClass("contactContainer_Active");},
			function() {$(contactContainerTr).removeClass("contactContainer_Active");}
		);
	
		// Обработка вызыва меню
		contactContainer.bind("myEventShowContactMenu", 
			function() {
				ContextMenuWin.css("top", mousePosition.pageY + "Px");
				ContextMenuWin.css("left", mousePosition.pageX + "Px");
				ContextMenuWin.fadeIn(200);
			});
	
		// Открыть окно сообщений по двойному щелчку 
		contactContainer.dblclick(
			function() {
				parentClass.showContactWindow(UIN);
				return false;
			});
		
		this.getContactStatusPicture().appendTo(contactStatus);
	};
	/**
	 * @return Ссылка на объект обена AJAX
	 * @type Object
	 */
	this.getAJAXQuery = function() 
	{
		return AJAXQuery;
	};
	/**
	 * @return Возвращает имя контакта
	 * @type string
	 */
	this.getContactName = function() 
	{
		if ((contactFields.name == undefined)||(contactFields.name == "")) {
			return UIN;
		}else{
			return contactFields.name;
		}
	};
	/**
	 * @return Возвращает UIN контакта
	 * @type string
	 */
	this.getContactUIN = function() 
	{
		return UIN;
	};
	/**
	 * @return Является ли контакт пользователем
	 * @type bool
	 */
	this.isUserProfile = function() 
	{
		return (parentClass.getUserProfileUIN() == UIN);
	};
	/**
	 * @return Возвращает объект статус картинки
	 * @type jquery
	 */
	this.getContactStatusPicture = function() 
	{
		var pictureName = parentClass.getStatuses().getStatusPicture(contactFields.status);
		var pictureAlt = parentClass.getStatuses().getStatusName(contactFields.status);
		var result = $('<div style="font-size: 5pt;color: #000;">');
		var src = "images/statuses/";
		
		if (pictureName != "") {
			
			if (contactFields.status != "STATUS_ONLINE") {
				var pictureOnline = parentClass.getStatuses().getStatusPicture("STATUS_ONLINE");
				$('<img class="contactStatusPictore">').attr("src", src + pictureOnline).appendTo(result);
			} 
		
			$('<img class="contactStatusPictore">').attr("src", src + pictureName).attr("alt", pictureAlt).appendTo(result);		
			return result;
		} else {
			var pictureName = parentClass.getStatuses().getStatusPicture("STATUS_OFFLINE");
			$('<img class="contactStatusPictore">').attr("src", src + pictureName).attr("alt", pictureAlt).appendTo(result);
		};
		
		return result; 
	};
	/**
	 * @return Объект окна контакта
	 * @type jquery
	 */
	this.getContactWin = function() 
	{
		return contactContainer;
	};
	/**
	 * Устанавливает имя контакта
	 */ 
	this.setContactName = function(newName) 
	{
		contactFields["name"] = newName;
		contactText.text(thisContact.getContactName());
	};
	/**
	 * Устанавливает статус контакта
	 */ 
	this.setContactStatus = function(newstatus) 
	{
		contactFields.status = newstatus;
		contactStatus.empty();
		thisContact.getContactStatusPicture().appendTo(contactStatus);
		
	};
	/**
	 * Устанавливает статус текст контакта (опционально)
	 */ 
	this.setContactStatusText = function(newStatusText) 
	{
		contactFields.statusText = newStatusText;
		// TODO дописать
	};
	/**
	 * Возвращает видимость контакта
	 */ 
	this.isVisible  = function() 
	{
		return isVisible;
	};
	/**
	 * Устанавливает видимость контакта
	 */ 
	this.setVisible = function(Visible) 
	{
		isVisible = Visible;
	};
	this.isOnline = function() 
	{
		return !((contactFields["status"] === "") || (contactFields["status"] === "STATUS_OFFLINE"));
	};
	
	// Инициализация класса
	this.__CContact();	
};

/**
 * Класс контакт листа
 * 
 * @constructor
 */ 
function CContactList(parentClass) {
	var userProfileUIN 				= undefined;
	var thisContactListClass 		= this;
	var contactList 				= new Array();
	var parentClass 				= parentClass;
	var AJAXQuery 					= parentClass.getAJAXQuery();
	var contactListStaartPosition 	= 5;
	var showOnlyOnlineContacts 		= true;
	var pictureOnlyOnline 			= "images/icons/contact_list_online.PNG";
	var pictureAllContacts 			= "images/icons/contact_list_all.PNG";
	// основные визуальные объекты класса 
	var mainContactListContainer 	= undefined;
	var contrloPanelV 				= undefined;
	var contrloPanel 				= undefined;
	var contactListArea 			= undefined;
	var clientControlV 				= undefined;
	var clientControl 				= undefined;
	var ButtonOnlineSwitch			= undefined;
	
	/**
	 * Конструктор класса
	 */
	this.__CContactList = function() 
	{
		mainContactListContainer = $('<div style="width: 100%;height: 100%; position: absolute;">');
		
		contrloPanelV = $('<div class="contactList_contrlPanelV"></div').appendTo(mainContactListContainer);
		contrloPanel = $('<div class="contactList_contrlPanel"></div').appendTo(mainContactListContainer);
		contactListArea = $('<div class="contactListArea"></div>').appendTo(mainContactListContainer);
		clientControlV = $('<div class="contactList_clientControlV"></div>').appendTo(mainContactListContainer);
		clientControl = $('<div class="contactList_clientControl"></div>').appendTo(mainContactListContainer);
		
		// Кнопка переключения видимости контактов
		ButtonOnlineSwitch = $('<img src="'+pictureOnlyOnline+'">').appendTo(contrloPanel).click(
			function() {
				var newState = thisContactListClass.toggleShowOnlyOnlineContacts();
				ButtonOnlineSwitch.attr("src", ((newState) ? pictureOnlyOnline : pictureAllContacts));
			});

		// Запрос контакт листа
		AJAXQuery.MakeAJAXQuery("getUserProfileInfo", undefined, this.ajaxUserProfileInfoReturn);
		AJAXQuery.MakeAJAXQuery("GetUserContactList", undefined, this.ajaxContactListReturn);
	};
	/**
	 * 
	 */
	this.getAJAXQuery = function() 
	{
		return AJAXQuery;
	};
	/**
	 * @return Возвращает окно контакт листа
	 * @type jquery
	 */ 	
	this.getContactListWin = function() 
	{
		return mainContactListContainer;
	};
	/**
	 * @return Возвращает класс статусов
	 * @type object
	 */ 
	this.getStatuses = function() 
	{
		return parentClass.statuses;
	};
	/**
	 * Отображает контакт лист
	 */
	this.refreshContactList = function() 
	{
		// TODO тут надо допиать какую-нибудь мега сортировку...
		var pos = contactListStaartPosition;		
		for (var i=0; i<contactList.length; i++) {
			var currentContact = contactList[i];

			if ((currentContact.isOnline()) || (! showOnlyOnlineContacts)) {
				if (!currentContact.isUserProfile()) {
					currentContact.getContactWin().css("top", pos).show();
					//pos+=contactList[i].getContactWin().height() + 3;
					pos+=20; // TODO ! Вот тут АФФИГЕННО медленно работает
				} 
			} else {
				currentContact.getContactWin().hide();
			}; 
		};
	};
	/**
	 * Переключает режим отображать все контакты / только Online контакты
	 */
	this.toggleShowOnlyOnlineContacts = function() 
	{
		showOnlyOnlineContacts = !showOnlyOnlineContacts;
		thisContactListClass.refreshContactList();
		return showOnlyOnlineContacts; 
	};
	/**
	 * @return Возвращает UIN профиля пользователя
	 * @type string
	 */
	this.getUserProfileUIN = function() 
	{
		return userProfileUIN;
	};
	/**
	 * Устанавливает UIN профиля пользователя
	 */
	this.setUserProfileUIN = function(newUIN) 
	{
		userProfileUIN = newUIN;
	};
	/**
	 * Открывает и активизирует окно сообщений контакта
	 */
	this.showContactWindow = function(UIN) 
	{
		parentClass.createNewWindow(UIN);
		parentClass.activateWindow(UIN);
	};
	/**
	 * Добавляет новый контакт
	 * @return Возвращает объект нового контакта
	 * @type object
	 */ 
	this.addContact = function(UIN) 
	{
		var newContact = new CContact(thisContactListClass, UIN);
		contactList[contactList.length] = newContact;
		newContact.getContactWin().hide().appendTo(contactListArea);
		return newContact;
	};	
	/**
	 * Проверяем существует-ли контакт с таким UIN'ом 
	 * @type bool
	 */ 
	this.contactExist = function(UIN) 
	{
		for (var i=0; i<contactList.length; i++) {
			if (contactList[i].getContactUIN() == UIN) {
				return true; 
			}
		}
		return false;
	};
	/**
	 * Возвращает класс контакта (если нет такого, то создается новый контакт)
	 * @return Класс контакта
	 * @type object
	 */	
	this.getContact = function(UIN) 
	{
		for (var i=0; i<contactList.length; i++) {
			if (contactList[i].getContactUIN() == UIN) {
				return contactList[i]; 
			}
		}
		return this.addContact(UIN);
	}; 
	/**
	 * Возвращает имя контакта по UIN'у
	 * @return Имя контакта
	 * @type string
	 */
	this.getContactName = function(UIN) 
	{
		return this.getContact(UIN).getContactName();
	};
	/**
	 * @return Стутус картинка контакта
	 * @type string
	 */
	this.getContactStatusPic = function (UIN) 
	{
		return this.getContact(UIN).getContactStatusPicture();
	};
	/**
	 * Вызывается при успшном получении данных с сервера
	 * @private
	 */
	this.ajaxContactListReturn = function(xml) 
	{
		var contacts = $("contact_list > contact",xml);
		var currentElement = undefined;
		var last_modified = $("contact_list",xml).attr('last_modified');
		
		if (contacts.length != 0) {
			AddLogMessage('Ajax query return: ' + contacts.length + ' contacts');
			for (var i=0; i<contacts.length; i++) {
				currentElement = contacts.eq(i);
				var contact = thisContactListClass.getContact(currentElement.attr('uin'));
				contact.setContactName(currentElement.attr('name'));
				contact.setContactStatus(currentElement.attr('status'));
			}
		}
		// И собственно покажем этот самый контакт лист 
		thisContactListClass.refreshContactList();
		AJAXQuery.MakeAJAXQuery("GetUserContactList",{last_modified : last_modified}, this.ajaxContactListReturn);
	};
	/**
	 * вызывается при успешном получении данных с сервера о профиле пользователя
	 */
	this.ajaxUserProfileInfoReturn = function(xml) 
	{
		var userProfileInfo = $("data > userprofile",xml);
		userProfileUIN = userProfileInfo.attr('uin');
		var contact = thisContactListClass.getContact(userProfileInfo.attr('uin'));
		contact.setContactName(userProfileInfo.attr('name'));
		contact.setContactStatus(userProfileInfo.attr('status'));
		AJAXQuery.setRefreshTime(userProfileInfo.attr('clientrefreshtime')*1000);
	};
	
	// Инициализация класса
	this.__CContactList();
};

/**
 * Класс области ввода сообщения
 * 
 * @param UIN string
 * @param ParentObject CTabsWindow
 */
function CChatArea(UIN, ParentObject) 
{
	var ThisChatClass = this;
	var WinNum        = UIN;
	/**
	 * @type CTabsWindow
	 */
	var ParentObject  = ParentObject;
	// Визуальные объекты
	var maindiv 	= undefined;
	var textdiv 	= undefined;
	var textarea 	= undefined;
	
	/**
	 * Конструктор класса
	 */
	this.__CChatArea = function ()
	{
		maindiv = $('<div style="position: absolute;width:100%;height: 100%;">');
		textdiv = $('<div class="chatArea_UserMessageText">').appendTo(maindiv);
		textarea = $('<textarea class="chatArea_UserMessageText1" rows="1" cols="50"></textarea>').text("Test it! " + UIN).appendTo(textdiv);
		// onkeypress="onkeypress_event(event)"
	
		button = $('<button type="submit" class="chatArea_ButtonSend">Отправить</button>').
				click( function() {ParentObject.addMessage();}).
				appendTo(maindiv);
	};
	/**
	 * @return Текст сообщения пользователя (из поля ввода)
	 * @type string
	 */	
	this.getMessageText = function() 
	{
		return textarea.attr("value"); 
	};
	/**
	 * Устанавливает теест сообщения пользователя
	 */
	this.setMessageText = function(messageText) 
	{
		textarea.attr("value", messageText);
	};
	/**
	 * Устанавливает фокус на поле ввода
	 */
	this.ActivateInputArea = function() 
	{
		textarea.focus();
	};
	/**
	 * @return Объект окна области ввода
	 * @type jquery
	 */
	this.GetChatTableWin = function() 
	{
		return maindiv;
	};
	
	// Инициализация класса
	this.__CChatArea();
	
}; // CChatArea

// ** Класс сообщения
// @parentClass	CContactChatWindow
// @from		int 
// @message		str
function CMessage(parentClass, contact, message) {
	var parentClass = parentClass;
	var outputStyles = parentClass.getOutputStyles(); 
	// Возвращает класс стилей отображения
	this.getOutputStyles = function() {
		return outputStyles;
	};
	
	var mainDiv = $("<div class='chatArea_message'>"); //</div>
	var contactInfo = $("<div class='chatArea_userUIN'>").text(contact.getContactName()).appendTo(mainDiv);
	var messageText = $("<div class='chatArea_message_text'></div>").text(message).appendTo(mainDiv);
	
	// Заменим перевод строки и псевдотеги смайликов на HTML коды  
	message = messageText.html();
	message = message.replace(/\n/g, "<BR>");
	message = message.replace(/\[smile_image src="(.*?)" txt="(.*?)"\]/g, "<span title='$2'><img src='$1'></span>");
	messageText.html(message);

	contactInfo.css('color', (contact.isUserProfile()) ? outputStyles.getValue("usernamecolor") : outputStyles.getValue("contactnamecolor"));
	messageText.css('color', outputStyles.getValue("messagecolor"));
	
	mainDiv.hover(
		function(){
			$(this).addClass("chatArea_message_active");
		},
		function(){
			$(this).removeClass("chatArea_message_active");
		}
	);
	
	// Возвращает окно сообщения
	this.getMessageWin = function() {
		return mainDiv; 
	};
}; // CMessage

function CTabsWindow(parentClass) 
{
	var thisTabsClass 	= this;
	var parentClass 	= parentClass;
	var contactList 	= parentClass.getContactList();
	var AJAXQuery 		= parentClass.getAJAXQuery();
	var outputStyles 	= parentClass.getOutputStyles(); 
	var blinkIsActive 	= false;
	
	var tabs 			= Array();
	var startPos 		= 20;
	var currentPos 		= startPos;

	var ChatInputHeight = 100;
	var messagesArray	= new Array();
	
	// Visual elemetnts
	var mainDiv 		= undefined;
	var scrollLeft 		= undefined;
	var scrollRight 	= undefined;
	
	
	this.__CTabsWindow = function() 
	{
		mainDiv = $("<div class='tab_background'></div>");
		
		// Кнопочки прокрутки вкладок
		scrollLeft = 
			$("<img src='images/button-right.PNG' style='position: absolute;right:0px;top:5px;z-index: 100;'></button>")
			.click(function() {thisTabsClass.scrollTabs(-50);})
			.hover(function() {$(scrollLeft).attr("src", "images/button-right_active.PNG");},
				   function() {$(scrollLeft).attr("src", "images/button-right.PNG");})		
			.appendTo(mainDiv);

		scrollRight = 
			$("<img src='images/button-left.PNG' style='position: absolute;left:0px;top:5px;z-index: 100;'></button>")
			.click(function() {thisTabsClass.scrollTabs(50);})
			.hover(
				function () {$(scrollRight).attr("src", "images/button-left_active.PNG");},
				function () {$(scrollRight).attr("src", "images/button-left.PNG");})		
			.appendTo(mainDiv);
	};

	/**
	 * @return Возвращает класс стилей отображения
	 * @type object
	 */ 
	this.getOutputStyles = function() 
	{
		return outputStyles;
	};
	/**
	 * Создает новое сообщение
	 */ 
	this.createNewMessage = function(contactUIN, messageText, mode, messagesWindow) 
	{
		var newMessage = new CMessage(thisTabsClass, contactList.getContact(contactUIN), messageText);
		var messageWin = newMessage.getMessageWin();
		
		if (mode === 1) {
			messageWin.prependTo(messagesWindow);
		} else {
			messageWin.appendTo(messagesWindow);
		}
		
		messagesArray[messagesArray.length] = newMessage;
		messageWin[0].scrollIntoView(false);
		return newMessage; 
	};
	/**
	 * Отправка нового сообщения
	 */  
	this.addMessage = function() 
	{
		var messageText = ChatArea.getMessageText();
		thisTabsClass.createNewMessage(contactList.getUserProfileUIN(), messageText);
		AJAXQuery.addMessageForSend(UIN, messageText);
	};

	/**
	 * Вызывается при получении данных с сервера (заполнение нескольких последних сообщений)
	 */ 
	var ajaxHistoryMessagesReturn = function(xml, UIN) 
	{
		var newMessagesRes = $("messages_log[@uin=" + UIN + "] > message",xml);
		var currentElement = undefined;
		var tabNum = getTabNumByUIN(UIN);
		AddLogMessage('Ajax query return: ' + newMessagesRes.length + ' messages from history', ((tabNum == undefined) ? 1 : undefined));
		
		// Такой вкладки нет, возможно мы ее уже закрыли
		if (tabNum == undefined) {
			return;
		}
		
		// Отделим последние сообщения черточкой
		var oldMessagesSeparator = undefined;
		if ( newMessagesRes.length != 0 ) {
			oldMessagesSeparator = $('<hr class="charArea_oldMessagesSeparator">').prependTo(tabs[tabNum].messagesWindow);
		}
		for (var i=0; i<newMessagesRes.length; i++) {
			currentElement = newMessagesRes.eq(i);
			thisTabsClass.createNewMessage(currentElement.attr('uin'), currentElement.text(),1, tabs[tabNum].messagesWindow);
		}
		
		if (oldMessagesSeparator != undefined) {
			oldMessagesSeparator[0].scrollIntoView(false);
		}
	};
	/**
	 * @return Возвращает корректную позицию вкладки
	 * @type int
	 */ 	
	var getPosition = function (tabNum) 
	{
		var pos = currentPos;
		for (var i=0; i<tabs.length; i++) {
			if (tabNum == i) {
				return pos;
			}
			pos+= tabs[i].container.width() + 1;
		}
		return pos;
	};
	/**
	 * @return Возвращает номер вкладки по UIN'у
	 * @type int
	 */ 
	var getTabNumByUIN = function (UIN) 
	{
		for (var i=0; i<tabs.length; i++) {
			if (tabs[i].UIN == UIN) {
				return i;
			}
		}
		return undefined;
	};
	/**
	 * @return Объект окна
	 * @type jquery
	 */
	this.getTabsWin = function() 
	{
		return mainDiv;
	};
	/**
	 * Устанавливает начальное положение вкладок
	 */ 
	this.scrollTabs = function(newPos) 
	{
		var newCurrentPos = currentPos + newPos;

		if (newCurrentPos > startPos) {
			newCurrentPos = startPos;
		}
		if (((getPosition()+newPos+80) < mainDiv.width())&&(newPos<0)) {
			return undefined;
		} 	
	
		currentPos = newCurrentPos;
		this.resizeAllTabs(100);
	};
	/**
	 * Подгоняет положение вкладок при закрытии
	 */  
	this.resizeAllTabs = function(speed) 
	{
		var scrollSpeed = (speed == undefined) ? 400 : speed;  
		for (var i=0; i<tabs.length; i++) {
			tabs[i].container.animate({left:getPosition(i)+"px"}, scrollSpeed);
		}
	};
	/**
	 * Всякие обработчики для анимации и функционала кнопочек...
	 */
	var setTabProperties = function(tabObject, UIN) 
	{
		var TabContainer = tabObject.container; 
		var button_close = tabObject.button_close;
		
		// Переключение подсветка кнопки закрытия...  		
		button_close.hover(
			function () {
				$(button_close).attr("src", "images/close_active.PNG");
			},
			function () {
				$(button_close).attr("src", "images/close_not_active.PNG");
			}
		);

		// Подсветка вкладок
		TabContainer.hover(
			function () {
				if ($(TabContainer).attr("isBlinked") == 1) {
					return;
				} 
			
				if ($(TabContainer).attr("isActive") == 0) {
					$(TabContainer).addClass("tab_hover");
					$(button_close).show();
				}
			},
			function () {
				if ($(TabContainer).attr("isBlinked") == 1) {
					return;
				} 
			
				$(TabContainer).removeClass("tab_hover");
				if (($(TabContainer).attr("isActive") == 0)) {
					$(button_close).hide();
				}
			}
		);
		TabContainer.bind("onBlinkTimer", 
			function(event, binkMode) {
				if (binkMode == undefined) { // Нужно просто убрать что вкладки мигает
					TabContainer.attr("isBlinked", 0);
					TabContainer.removeClass("tab_active_newMessage");
					TabContainer.removeClass("tab_not_active_newMessage");
					return;
				} else {
					bl1 = binkMode; 
				}
			
				if ($(TabContainer).attr("isActive") == 1) {
					if (bl1) {
						TabContainer.addClass("tab_active_newMessage");
					} else {
						TabContainer.removeClass("tab_active_newMessage");
					}
				} else {
					if (bl1) {
						TabContainer.addClass("tab_not_active_newMessage");
					} else {
						TabContainer.removeClass("tab_not_active_newMessage");
					}
				}
			}
		);
		
		// обработчики...
		tabObject.text.click(function() {parentClass.activateWindow(UIN);});
		tabObject.button_close.click(function() {parentClass.closeWindow(UIN);});
	};
	/**
	 * Создает новую вкладку (самая важная функция)
	 */ 
	this.createNewTab = function(UIN) 
	{
		var tabNum = tabs.length;
		
		var TabContainer = $("<div class='tab_not_active'></div>").css("left", getPosition() + "px").attr("isActive", 0).appendTo(mainDiv);
		var status 	= $("<div class='tab_status'></div>").appendTo(TabContainer);
		// Приделываем статус к контакту
		contactList.getContactStatusPic(UIN).appendTo(status);
		var text	= $("<div class='tab_text'></div>").appendTo(TabContainer);
		var close 	= $("<div class='tab_close'></div>").appendTo(TabContainer);
		text.text(contactList.getContactName(UIN));
		
		var button_close = $("<img src='images/close_not_active.PNG' border=0>").hide().appendTo(close);
		
		// Chat area
		var mainChatAreaContainer	= $("<div class='chatArea_mainWindow'></div>"); //  id='"+UIN+"'
		
		var messagesWindow = $("<div class='chatArea_messagesWindow'></div>").css("bottom", ChatInputHeight+"px");
		var inputwin = $("<div class='chatArea_inputWindow'></div>").css("height", ChatInputHeight+"px");
		
		var ChatArea = new CChatArea(UIN, thisTabsClass);
		ChatArea.GetChatTableWin().appendTo(inputwin);
		
		messagesWindow.appendTo(mainChatAreaContainer);
		inputwin.appendTo(mainChatAreaContainer); 
		mainChatAreaContainer.appendTo($("#MainParentWin"));
		
		tabs[tabNum] = {UIN                   : UIN, 
						container             : TabContainer, 
						status                : status, 
						text                  : text, 
						close                 : close, 
						button_close          : button_close, 
						newMessages           : undefined,
						mainChatAreaContainer : mainChatAreaContainer,
						messagesWindow        : messagesWindow};

		setTabProperties(tabs[tabNum], UIN);
		// Запрос нескольких последних сообщений контакта 
		AJAXQuery.MakeAJAXQuery("getContactHistory",{contactUIN:UIN},ajaxHistoryMessagesReturn, UIN);
	};
	/**
	 * Активирует вкладку
	 */ 
	this.activateTab = function(UIN) 
	{
		var tabNum = getTabNumByUIN(UIN);

		if (tabs[tabNum].newMessages !== undefined) {
			tabs[tabNum].newMessages = false;
			tabs[tabNum].container.trigger("onBlinkTimer");
		};
		
		tabs[tabNum].container.addClass("tab_active");
		tabs[tabNum].container.attr("isActive", 1);
		tabs[tabNum].container.removeClass("tab_hover");
		tabs[tabNum].button_close.show();
		
		tabs[tabNum].mainChatAreaContainer.show();
		
	};
	/**
	 * Деактивирует вкладку
	 */ 
	this.deactivateTab = function(UIN) 
	{
		var tabNum = getTabNumByUIN(UIN);
		tabs[tabNum].container.removeClass("tab_active");
		tabs[tabNum].container.attr("isActive", 0);
		tabs[tabNum].button_close.hide();
		tabs[tabNum].container.trigger("onBlinkTimer");

		tabs[tabNum].mainChatAreaContainer.hide();
	};
	/**
	 * Закрывает вкладку
	 */ 
	this.closeTab = function(UIN) 
	{
		var tabNum = getTabNumByUIN(UIN);
		tabs[tabNum].container.fadeOut(400, function() {$(this).remove();});
		tabs.splice(tabNum,1);
		this.resizeAllTabs();
	};
	/**
	 * Режим: получено новое сообщение
	 */
	this.setNewMessages = function(UIN) 
	{
		var tabNum = getTabNumByUIN(UIN);
		tabs[tabNum].newMessages = true;
		tabs[tabNum].container.attr("isBlinked", 1);
	};
	/**
	 * Мигание вкладок
	 */
	this.blinkTabs = function() 
	{
		blinkIsActive = !blinkIsActive;
	
		for (var i=0; i<tabs.length; i++) {
			var currentTab = tabs[i];
			if (currentTab.newMessages) {
				currentTab.container.trigger("onBlinkTimer", blinkIsActive);
			};
		};
	};
	// Конструктор класса
	this.__CTabsWindow();
	
}; // CTabsWindow

/**
 * Основной класс оконных вкладок
 * 
 * TODO Переделать тут все нафиг, а то очень криво....
 */  
function CMainMessagesWindow() {
	var thisMainMessagesWindow = this;
	var allWindows = new Array();
	var currentActiveWindow = undefined;
	var mainParentWin = "#MainParentWin";
	var timerVaribleStr = "";
	var timerPeriod = 2000;

	// Создадим класс обмена обмена сообщениями CAJAX 	
	var AJAXQuery = new CAJAX(thisMainMessagesWindow);
	
	// Возвращает объект обмена с сервером. 
	this.getAJAXQuery = function() {
		return AJAXQuery;
	};
	
	// Создадим класс стилей
	var outputStyles = new COutputStyles(thisMainMessagesWindow);
	
	// Создадим класс статусов
	var statuses = new CStatuses(thisMainMessagesWindow);
	// Что-бы можно было обращаться напрямую к статусам
	this.statuses = statuses;
	
	// Создадим класс контакт листа
	var contactList = new CContactList(thisMainMessagesWindow);
	contactList.getContactListWin().appendTo($("#MainContactList"));
	
	// Что-бы можно было обращаться напрямую к контактлисту...
	this.contactList = contactList;

	// Возвращает объект контакт-листа	
	this.getContactList = function() {
		return contactList;
	};
	
	// Возвращает класс стилей отображения
	this.getOutputStyles = function() {
		return outputStyles;
	};
	
	// Создадим окно с закладками
	var tabs = new CTabsWindow(thisMainMessagesWindow);
	tabs.getTabsWin().appendTo($("#MainWinBar"));

	// Возвращает номер окна в массиве по UIN'у	
	function getWinNumByUIN(UIN) {
		for (var i=0; i<allWindows.length; i++) {
			if (allWindows[i].UIN == UIN) {
				return i;
			}
		}
		return undefined;
	}
	
	// Переключает текущее окно 
	this.activateWindow = function(UIN) {
		if (currentActiveWindow != undefined) {
			tabs.deactivateTab(currentActiveWindow);
			//allWindows[getWinNumByUIN(currentActiveWindow)].win.deactivateWindow();
		}
		
		//allWindows[getWinNumByUIN(UIN)].win.activateWindow();
		tabs.activateTab(UIN);
		currentActiveWindow = UIN;
	};

	// Создает окно сообщений
	this.createNewWindow = function(UIN, newMessages) {
		var win = getWinNumByUIN(UIN);
		
		newMessages = (newMessages == undefined) ? false : newMessages;
		// Такое окно уже есть		
		if (win != undefined) {
			if (newMessages) {
				tabs.setNewMessages(UIN);
			}	
		
			return win;
		}
	
		var newWinNumber = allWindows.length;
//		var newWindow = new CContactChatWindow(thisMainMessagesWindow, UIN, newWinNumber);
//		newWindow.getChatAreaWin().appendTo($(mainParentWin));
		
		tabs.createNewTab(UIN);
		//allWindows[newWinNumber] = {UIN: UIN, win: newWindow};
		allWindows[newWinNumber] = {UIN: UIN};
		
		if (currentActiveWindow == undefined) {
			this.activateWindow(UIN);
		}

		if (newMessages) {
			tabs.setNewMessages(UIN);
		}	
		
		return newWinNumber;
	};

	// Закрывает окно сообщения	
	this.closeWindow = function(UIN) {
		var WinNum = getWinNumByUIN(UIN);
		//alert(WinNum);
		if (UIN == currentActiveWindow) {
			if (allWindows.length == 1) {
				currentActiveWindow = undefined;
			} else {
				var NewWin = (WinNum == 0) ?  1 : (WinNum - 1);
				this.activateWindow(allWindows[NewWin].UIN); 
			} 
		}
		
		//allWindows[WinNum].win.getChatAreaWin().remove();
		tabs.closeTab(UIN);
		allWindows.splice(WinNum, 1);
	};
	
	this.newMessage = function(UIN, text) {
		var mess_winnum = this.createNewWindow(UIN, true);
		//getWinNumByUIN(currentActiveWindow) != mess_winnum
		//this.activateWindow(mess_winnum);
		allWindows[mess_winnum].win.createNewMessage(UIN, text);
	};

	this.BlinkTimer = function() {
		tabs.blinkTabs();
		setTimeout(timerVaribleStr, timerPeriod);
	};
	
	this.startBlinkTimer = function(str, per) {
		timerVaribleStr = str;
		timerPeriod = per;
		this.BlinkTimer();
	};
};

/**
 * Класс окна
 * 
 * @constructor
 */
function CWindow (parentWin, winID, winStyleInput) {
	var thisWindow = this;
	var isOpened = true;

	if (winID == undefined) {
		alert("ERROR! Wrang Window ID!");
		return;
	}
	
	var wind = $('<div class="winBody"></div>').attr('id', winID);
	
	// Возвращает статус окна (открыто/закрыто)
	this.isOpened = function () {
		return isOpened;
	};
	
	// Показывает окон
	this.showWindow = function() {
		if (!isOpened) {
			wind.fadeIn(300);
			isOpened = true; 
		}
	}; 

	// Скрывает окно
	this.hideWindow = function() {
		//alert(isOpened);
		if (isOpened) {
			wind.fadeOut(300);
			isOpened = false;
		}
	};

	// Зададим размеры окна по умолчанию, если они не заданы
	winStyle = 
		{
			top:10, 
			left:10, 
			width:600, 
			height:400,
			minWidth: 400,
			minHeight: 250,
			maxWidth: 1000,
			maxHeight: 800,
			isClosable: true,
			isMovable: true,
			isSizable: true,
			title : undefined,
			content : undefined
		};
	
	if (winStyleInput != undefined) {
		for (var property in winStyleInput) {
			winStyle[property] = winStyleInput[property];
		}
	}
	
	//winStyle.isCloseable = true;
	//alert(winStyle.isCloseable)

	wind.css('top', winStyle.top + "px");
	wind.css('left', winStyle.left + "px");
	wind.css('width', winStyle.width + "px");
	wind.css('height', winStyle.height + "px");
	
	var windowTop = $('<div class="winTitle"></div>').appendTo(wind);
	//var windowDrag = $('<div class="winDrag"></div>').appendTo(wind);
	var windowDragID = '#'+winID+' .winTitle';
	
	if (winStyle.title != undefined) {
		windowTop.text(winStyle.title);
	} 
	
	// Если окон закрываемое, то нарисуем кнопочку
	if (winStyle.isClosable) {
		var windowDrag = $('<div class="winDrag"></div>').appendTo(wind);
		windowDragID = '#'+winID+' .winDrag';
		
		var buttonclose = $('<button class="winClose"></button>').appendTo(windowTop);
		buttonclose.click(function(){
			thisWindow.hideWindow();
			});
	}

	var windowContent = $('<div class="winContent"></div>').appendTo(wind);
	var windowBottom = $('<div class="winBottom"></div>').appendTo(wind);

	var winSizeHandlers = {};
	if ((winStyle.isSizable) && (winStyle.isMovable)) {
		var windowResize = $('<IMG src="images/resize.PNG" class="winResize">').appendTo(windowBottom);
		winSizeHandlers ={se: '#'+winID+' .winResize'};		
	}
	
	// Прикрепляем контент, если есть что прикреплять =)
	if (winStyle.content != undefined) {
		winStyle.content.appendTo(windowContent);
	}	

	wind.appendTo(parentWin);
	
	// А может оно вообще не будет двигаться! 
	if (winStyle.isMovable) {
	
		wind.Resizable(
			{
				minWidth: winStyle.minWidth,
				minHeight: winStyle.minHeight,
				maxWidth: winStyle.maxWidth,
				maxHeight: winStyle.maxHeight,
				dragHandle: windowDragID,
				handlers: winSizeHandlers,
				onResize : function(size, position) {
				},
				onDrag : function (x,y) { // Тут что-бы мы за границы окна не вывалились...
					// TODO В IE эта шняга нифига не работает...
					var newPos = {x:x,y:y};
					var width = $(window).width() - wind.width();  
					var height = $(window).height() - wind.height();
					
					if (x<0) {newPos.x = 0;}
					if (y<0) {newPos.y = 0;}
					if (x>width) {newPos.x = width;}
					if (y>height){newPos.y = height;}
					
					return newPos; 
				}
			}
		);
	};
};

/**
 * Тут создаем классы и заставляем всю эту бадягу фунциклировать =)
 */
function documentReadyFunction() {
	if ($.browser.msie) {
		if ($.browser.version <= 6) { // C 7.0 еще будем пробовать как-нибудь бороться, а с этим ****** да-ж заморачиваться нехочу...
			$("body").html("<H1>This version of client not work with IE 6.0!  <small>sorry... :'(</small></H1>");
			return;
		}
	}
	
	$('<title>').text('Client [version 2.0 betta jQuery]').appendTo($('head'));

	// Правая кнопка мышки будет только там где я скажу! =)
	// Хотя это не совсем хорошая идея конечно.....
	// $('body').attr("oncontextmenu", "return false;");

	// Это для того что-бы всегда знать положение курсора мышки
	$(document).mousemove(function(e){mousePosition = e;});
	
	// Ширшина окон =)
	var winLogWidth = Math.round(($(document).width() - 240) * 0.4);
	var winChatWidth = Math.round(($(document).width() - 240) * 0.6);
	
	//var allWinHeight = 330;
	var allWinHeight = $(document).height()-20;
	
	// Прежде всего создадим окно лога.
	var winStyleLog	 = {top:10,				left:winChatWidth+230,		width:winLogWidth,	height:allWinHeight,
						minWidth: 200,		minHeight: 100,	maxWidth: 1000,					maxHeight: 800,
						isClosable: true,	isMovable: true,isSizable: true,
						title: "Log",	content: $('<div id="LogArea" class="log_LogArea">')};

	// Окно лога 
	var winLog = new CWindow($('body'),'__WindLog__',	winStyleLog);

	//**************************************************************************//
	//*** А дальше тут поша полная каша.... авторизация, и прочая лабуда.... ***//
	//**************************************************************************//

	/*var cont1 = $(''+
			'<table width="100%" border="0">'+
			'<tr><td width="70">User ID</td><td><input type="text"></td></tr>'+
			'<tr><td width="70">User pass</td><td><input type="password"></td></tr>'+
			'<tr><td width="70">User key</td><td><input type="password"></td></tr>'+
			'<tr><td width="70"></td><td align="right"><button>Log in</button></td></tr>'+
			'</table>');

	// Окно авторизации.
	var winStyleUser = {top:10,				left:10,		width:230,		height:155,
						isClosable: false,	isMovable: true,isSizable: false,
						title: "Select user profilr information", content:cont1};
	// Окно авторизации. 
	var winUser = new CWindow($('body'),'__WindUser__',	winStyleUser); */

	
	var winStyleList = {top:10,			left:winChatWidth+20,		width:200,		height:allWinHeight-90,
						minWidth: 150,	minHeight: 250,	maxWidth: 300,	maxHeight: 800,
						title: "Contact list", 
						content: $('<div ID="MainContactList"></div>')};

	var winStyleChat = {top:10,			left:10,		width:winChatWidth,		height:allWinHeight,
						minWidth: 400,	minHeight: 260,	maxWidth: 1000,	maxHeight: 800,
						title: "Chat",
						content: $('<div ID="MainWinBar"></div><div ID="MainParentWin"></div>')};

	// Окно сообщений
	var winChat = new CWindow($('body'), '__WindChatArea__', winStyleChat);

	// Окно контактов
	var winList = new CWindow($('body'),'__WindContactList__',	winStyleList);


	var buttons = $('<div style="width: 100%; text-align: center">');
	$('<button class="controlButtonOn">').text("Chat").click(function(){$(this).toggleClass("controlButtonOff"); (winChat.isOpened()) ? winChat.hideWindow() : winChat.showWindow();}).appendTo(buttons);
	$('<button class="controlButtonOn">').text("List").click(function(){$(this).toggleClass("controlButtonOff"); (winList.isOpened()) ? winList.hideWindow() : winList.showWindow();}).appendTo(buttons);
	$('<button class="controlButtonOn">').text("Log").click(function(){$(this).toggleClass("controlButtonOff"); (winLog.isOpened()) ? winLog.hideWindow() : winLog.showWindow();}).appendTo(buttons);
	
	var winStyleButtons= {top:allWinHeight-70,			left:winChatWidth+20,		width:200,		height:80,
						isClosable: false,	isMovable: true,isSizable: false,
						title: "Buttons",	content: buttons};

	// Окно кнопок открытия 
	var winButtons = new CWindow($('body'),'__WindButtons__',	winStyleButtons);
	
	mainMessagesWindow = new CMainMessagesWindow();
	mainMessagesWindow.getAJAXQuery().startTimer("mainMessagesWindow.getAJAXQuery()", 2000);
	mainMessagesWindow.startBlinkTimer("mainMessagesWindow.BlinkTimer()", 500);
	
	AddLogMessage('Client started.');
	if ($.browser.msie) {
		AddLogMessage('Work with IE not fully tested!',1);
	}
};

// Тут закипает работа =) Грубо говоря void main()   =)) 
$(document).ready(function() {documentReadyFunction();});
